// require('./redis/connect');
const connectDb = require('./db/connection')

const Koa = require('koa')
const session = require('koa-session');
const bodyParser = require('koa-bodyparser')
const helmet = require('koa-helmet') // https://github.com/venables/koa-helmet
const cors = require('koa2-cors')
const jwt = require('koa-jwt')
const xmlParser = require('koa-xml-body')

const useLogger = require('./modules/logger')
const { AppLog } = require('./modules/log')

const initRouter = require('./routes')

const { APP_PORT, DEBUG, JWT, ROUTE_WHITE_LIST, ADMIN_KEY } = require('./env')
const { genResponse } = require('./utils')

const app = new Koa()
app.keys = ['wow portal app keys']

app.use(async (ctx, next) => {
  try {
    await next()
  } catch (err) {
    ctx.status = err.status || 500
    ctx.body = genResponse(false, null, err.message)
    ctx.app.emit('error', err, ctx)
  }
})
app.use((ctx, next) => next().catch((err) => {
  if (err.status === 401) {
    ctx.status = 401
    ctx.body = {
      ok: false,
      data: null,
      msg: err.originalError ? err.originalError.message : err.message
    }
  } else {
    throw err
  }
}))
app.use(session(app))
app.use(async (ctx, next) => {
  if (ctx.path === '/favicon.ico') {
    ctx.status = 204
    return
  }
  await next()
})
app.use(helmet())
app.use(cors({
  origin (ctx) {
    if (DEBUG) {
      return '*'
    }
    const requestReferer = ctx.get('Referer')
    const requestOrigin = ctx.get('Origin')
    const refererWhiteList = [
    ]
    const permitted = refererWhiteList.some(referer => requestReferer.indexOf(referer) > -1)
    if (permitted) {
      return requestOrigin
    }
    throw new Error(`illegal request from:, ${requestOrigin}, ${requestReferer}`)
  }
}))
useLogger(app)

app.use(xmlParser({}))
app.use(bodyParser({}))
// ? 路由必须有返回，不然 Not Found
// ! 加密的数据通过 ctx.state 获取
// app.use(jwt({ secret: JWT.secret, cookie: JWT.name }).unless({ path: ROUTE_WHITE_LIST }))
initRouter(app)

app.on('error', (err, ctx) => {
  ctx.logger.error('server error', err)
})

async function bootstrap() {
  await connectDb()
  app.listen(APP_PORT, () => {
    AppLog(`SERVER START IN PORT: ${APP_PORT}.`)
    AppLog(`ADMIN ID: ${ADMIN_KEY}`)
  })
}

bootstrap()